home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Language/OS - Multiplatform Resource Library
/
LANGUAGE OS.iso
/
smaltalk
/
manchest.lha
/
MANCHESTER
/
usenet
/
st80_pre4
/
pbm.st
< prev
next >
Wrap
Text File
|
1993-07-24
|
7KB
|
262 lines
" NAME pbm
AUTHOR kww@cs.glasgow.ac.uk
FUNCTION Conversion between Forms and PBM
ST-VERSIONS 2.5
PREREQUISITES
CONFLICTS
DISTRIBUTION world
VERSION 1.1
DATE 14 May 1990
SUMMARY The following file-in supports the reading and writing of
Smalltalk Forms (here wrapped up in what I call an IconImage - a
simple way of naming a Form) into the Portable Bitmap file format.
"!
"
From: kww@cs.glasgow.ac.uk (Dr Kevin Waite)
Newsgroups: comp.lang.smalltalk
Subject: Conversion between Forms and PBM
Message-ID: <5238@vanuata.cs.glasgow.ac.uk>
Date: 14 May 90 17:33:39 GMT
Organization: Computing Sci, Glasgow Univ, Scotland
The following file-in supports the reading and writing of Smalltalk
Forms (here wrapped up in what I call an IconImage - a simple way of
naming a Form) into the Portable Bitmap file format. This format
(copyrighted by Jef Poskanzer) is a lowest-common denominator allowing
bitmap images to be sent over the mail, and converted between a whole
variety of different formats including PICT, GIF, MacPaint, Sun Icons,
Postscript, ASCII, etc. I wrote this utility to make use of the Sun
icon collection but have found it useful in taking images over from my
Macintosh as well. I hope you find it useful. Any comments on the
code (yes I know its a bit messy!!) are welcome.
BTW, PBM is a public domain utility available on (at least) a variety of
UNIX platforms. The following piece of code is perhaps not as lenient
of dodgy input as Poskanzer would like!!
Cheers,
Kevin
Email: kww@uk.ac.glasgow.cs (JANET)
kww%cs.glasgow.ac.uk@nsfnet-relay.ac.uk (INTERNET)
Address: Dept. of Computing Science, University of Glasgow,
17 Lilybank Gardens, Glasgow, United Kingdom. G12 8QQ
"
'From Objectworks for Smalltalk-80(tm), Version 2.5 of 29 July 1989
on 14 May 1990 at 6:25:56 pm'!
Object subclass: #IconImage
instanceVariableNames: 'name form '
classVariableNames: ''
poolDictionaries: ''
category: 'Icon-Browsing'!
IconImage comment:
'I represent a named graphical image. My instance variables
hold my name and the Form that is my graphical representation.
I support loading and saving using the Portable Bitmap format
and thereby onto other graphical formats via the many conversion
tools available in the PBM library.
The Portable Bitmap facility is copyright (c) 1988 by Jef Poskanzer.'!
!IconImage methodsFor: 'accessing'!
form
^form!
form: aForm
form := aForm.!
name
^name!
name: aString
name := aString.! !
!IconImage methodsFor: 'file-in/out'!
writePBMfile: fileName
"Saves the receiver on the file fileName in Portable Bitmap format.
See the class method pbmSyntax for details of the format."
| aStream bitMask wordCount bitCount bitsOnLine |
aStream := fileName asFilename writeStream.
aStream nextPutAll: 'P1'; cr.
aStream nextPutAll: '# Converted from Smalltalk Form on '.
aStream nextPutAll: Date today printString.
aStream nextPutAll: ' at ', Time now printString.
aStream cr.
aStream nextPutAll: self form width printString.
aStream space.
aStream nextPutAll: self form height printString.
aStream cr.
bitMask := Array new: 16.
1 to: 16 do: [:k | bitMask at: k put: (1 bitShift: (k-1))].
wordCount := self form width + 15 // 16 * self form height.
"The following two counters are used to ensure that newlines are
forced on the stream after every 70 characters and after every
row has been completed (unless the row is shorter than 70 chars)."
bitsOnLine := bitCount := 0.
1 to: wordCount do: [:index |
| endOfRow word bitNum bit |
word := self form bitsWordAt: index.
bitNum := 16.
endOfRow := false.
[bitNum = 0 or: [endOfRow]] whileFalse: [
bit := word bitAnd: (bitMask at: bitNum).
aStream nextPut: (bit = 0 ifTrue: [$0] ifFalse: [$1]).
bitsOnLine := bitsOnLine + 1.
bitsOnLine > 70 ifTrue: [
aStream cr.
bitsOnLine := 0.
].
bitNum := bitNum - 1.
endOfRow := (bitCount := bitCount + 1) = self form width.
].
endOfRow ifTrue: [
aStream cr.
bitCount := bitsOnLine := 0.
].
].
aStream close.! !
!IconImage methodsFor: 'initialisation'!
initialize
self name: 'an Image'.
self form: nil.! !
"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
IconImage class
instanceVariableNames: ''!
!IconImage class methodsFor: 'instance creation'!
new
^super new initialize!
pbmSyntax
"- A 'magic number' for identifying the file type. A pbm
file's magic number is the two characters 'P1'.
- Whitespace (blanks, TABs, CRs, LFs).
- A width, formatted as ASCII characters in decimal.
- Whitespace.
- A height, again in ASCII decimal.
- Whitespace.
- Width * height bits, each either '1' or '0', starting at
the top-left corner of the bitmap, proceding in normal
English reading order.
- The character '1' means black, '0' means white.
- Whitespace in the bits section is ignored.
- Characters from a '#' to the next end-of-line are ignored
(comments).
- No line may be longer than 70 characters."!
readImageFromPBMFile: fileName
"Answer an instance of IconImage initialized from a Portable Bit Map
file. The expected format of the file is in the method
IconImage class>pbmSyntax."
| aFile aStream width height bits form bitMask index shift image |
aFile := fileName asFilename.
aFile exists ifFalse: [^nil].
aStream := aFile readStream.
(aStream peek = $P)
ifFalse: [self error: 'Invalid magic number']
ifTrue: [aStream next].
(aStream peek = $1)
ifFalse: [self error: 'Invalid magic number']
ifTrue: [aStream next].
self skipPBMJunkOn: aStream.
width := Integer readFrom: aStream.
width > 0 ifFalse: [self error: 'Invalid width'].
self skipPBMJunkOn: aStream.
height := Integer readFrom: aStream.
height > 0 ifFalse: [self error: 'Invalid height'].
bits := WordArray new: (width + 15 // 16 * height).
form := Form new extent: width@height.
"Initialize an array of sixteen 16-bit numbers each with a single
unique bit set corresponding to a power of two. This will simplify
the setting of of pixel values within a compressed word."
bitMask := Array new: 16.
1 to: 16 do: [:k | bitMask at: k put: (1 bitShift: (k-1))].
index := 1.
1 to: height do: [:y | | word |
shift := 16.
word := 0.
1 to: width do: [:x |
self skipPBMJunkOn: aStream.
aStream atEnd ifTrue: [self error: 'Unexpected End-of-file'].
aStream next = $1
ifTrue: [word := word bitOr: (bitMask at: shift)].
shift := shift - 1.
shift = 0 ifTrue: [ "End of the current word?"
bits at: index put: word.
index := index + 1.
shift := 16.
word := 0.
].
].
shift < 16 ifTrue: [ "A partly filled words needs to be saved."
bits at: index put: word.
index := index + 1.
].
].
form bits: bits.
aStream close.
image := self new form: form.
image name: fileName.
^image! !
!IconImage class methodsFor: 'parsing utilities'!
skipPBMJunkOn: aStream
"This method removes any superfluous characters
from the input stream."
| char |
[char := aStream peek.
char = $# ifTrue: ["Start of a comment. Skip to end-of-line."
| foundNL |
foundNL := (aStream skipUpTo: Character cr) notNil.
foundNL ifFalse: ["Must be EOF" ^self].
char := aStream peek.
].
aStream atEnd not and: [char isSeparator]] whileTrue: [aStream next].! !